package cn.monkey.family.server.domain.uc.auth;

import cn.monkey.family.data.jwt.JwtProperties;
import cn.monkey.family.data.uc.user.role.UserRoleMapper;
import cn.monkey.family.rbac.dsl.http.HttpRequestPredicateFactory;
import cn.monkey.family.rbac.dsl.http.jakarta.DefaultJakartaHttpServletRequestPredicateFactory;
import cn.monkey.family.server.domain.uc.auth.verifycode.CodeRepository;
import cn.monkey.family.server.domain.uc.auth.verifycode.SimpleCacheableCodeRepository;
import cn.monkey.family.server.domain.uc.auth.jwt.JWTAuthorizationManager;
import cn.monkey.family.server.domain.uc.auth.password.DefaultPasswordEncoder;
import cn.monkey.family.server.domain.uc.auth.password.PasswordEncoder;
import cn.monkey.family.server.domain.uc.auth.session.UserSessionRepository;
import cn.monkey.family.server.domain.uc.auth.token.CacheableRequestContextRepository;
import cn.monkey.family.server.domain.uc.auth.token.DownloadTemporaryTokenFilter;
import cn.monkey.family.server.domain.uc.auth.token.RequestContextRepository;
import cn.monkey.family.server.domain.uc.org.role.OrgRoleRepository;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AuthConfig {

    @Bean
    AuthorizeFilterChain authorizeFilterChain(ObjectProvider<AuthorizeFilter> filters) {
        return new DefaultAuthorizeFilterChain(filters.orderedStream().toList());
    }


    @Bean
    RequestContextRepository requestContextRepository(CacheManager cacheManager) {
        return new CacheableRequestContextRepository(cacheManager);
    }

    @Bean
    @ConfigurationProperties(prefix = "monkey.jwt")
    JwtProperties jwtProperties() {
        return new JwtProperties();
    }

    @Bean
    CodeRepository codeRepository(CacheManager cacheManager) {
        return new SimpleCacheableCodeRepository(cacheManager);
    }

    @Bean
    PasswordEncoder passwordEncoder() {
        return new DefaultPasswordEncoder();
    }

    @Bean
    AuthorizationManager authorizationKeyManager(JwtProperties jwtProperties) {
        return new JWTAuthorizationManager(jwtProperties);
    }

    @Bean
    IAfterAuthorizeHandler afterSignInHandler(AuthorizationManager authorizationKeyManager,
                                              UserRoleMapper userRoleMapper,
                                              OrgRoleRepository orgRoleRepository,
                                              UserSessionRepository userSessionRepository) {
        return new AfterAuthorizeHandler(authorizationKeyManager, userRoleMapper, orgRoleRepository, userSessionRepository);
    }


    @Bean
    HttpRequestPredicateFactory<HttpServletRequest> httpRequestPredicateFactory() {
        return new DefaultJakartaHttpServletRequestPredicateFactory();
    }

    @Bean
    FilterRegistrationBean<DownloadTemporaryTokenFilter> downloadTemporaryTokenFilterRegistrationBean(RequestContextRepository requestContextRepository) {
        FilterRegistrationBean<DownloadTemporaryTokenFilter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
        filterFilterRegistrationBean.setFilter(new DownloadTemporaryTokenFilter(requestContextRepository));
        filterFilterRegistrationBean.setOrder(-1);
        return filterFilterRegistrationBean;
    }
}
